package com.example.redis.redEnvelope.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
public class RedEnvelopeController {
    public static final String RED_ENVELOPE_KEY = "red_envelope";
    public static final String RED_ENVELOPE_USER_KEY = "red_envelope_user";

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/send/{totalMoney}/{count}")
    public String sendRedEnvelope(
            @PathVariable("totalMoney") String totalMoney,
            @PathVariable("count") Integer count) {
        BigDecimal total = new BigDecimal(totalMoney);
        // 补充拆红包逻辑：二倍均值算法
//        BigDecimal each = total.multiply(new BigDecimal("0.5")).divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP);
        BigDecimal[] split = split(total, count);
        for (int i = 0; i < split.length; i++) {
            redisTemplate.opsForList().leftPush(RED_ENVELOPE_KEY, split[i]);
        }
        return "发送成功！";
    }

    // 抢红包逻辑
    @GetMapping("/grab/{count}")
    public HashMap<String, String> grabRedEnvelope(@PathVariable("count") Integer count) throws InterruptedException {
        ExecutorService threadPool = Executors.newFixedThreadPool(count);
        CountDownLatch countDownLatch = new CountDownLatch(count);
        for (int i = 0; i < count; i++) {
            threadPool.execute(() -> {
                String userId = Thread.currentThread().getName();
                if (redisTemplate.opsForHash().hasKey(RED_ENVELOPE_USER_KEY, userId)) {
                    System.out.println("用户：" + userId + "已抢到红包, 不可重复抢");
                    return;
                }
                BigDecimal amount = (BigDecimal) redisTemplate.opsForList().rightPop(RED_ENVELOPE_KEY);
                if (amount != null) {
                    redisTemplate.opsForHash().put(RED_ENVELOPE_USER_KEY, userId, amount);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        threadPool.shutdown();
//        Set keys = redisTemplate.opsForHash().keys(RED_ENVELOPE_USER_KEY);
//        keys.iterator();
        Set keys = redisTemplate.opsForHash().keys(RED_ENVELOPE_USER_KEY);
        HashMap<String, String> map = new HashMap<>();
        keys.forEach(key -> map.put(key.toString(), redisTemplate.opsForHash().get(RED_ENVELOPE_USER_KEY, key).toString()));
        return map;
    }

    @GetMapping("/grab")
    public String grabRedEnvelope() {
        return null;
    }


    // 二倍均值算法
    public static BigDecimal[] split(BigDecimal total, Integer count) {
        // 记录余额
        BigDecimal balance = total;
        // 剩余红包数
        Integer rest = count;

        BigDecimal[] bigDecimals = new BigDecimal[count];

        for (int i = 0; i < count - 1; i++) {
            BigDecimal each = balance
                    .multiply(new BigDecimal(2))
                    .divide(new BigDecimal(rest), 2, BigDecimal.ROUND_HALF_UP)
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
            rest--;
            double v = each.doubleValue();
            double v1 = Math.random() * v;
            bigDecimals[i] = new BigDecimal(v1).setScale(2, BigDecimal.ROUND_HALF_UP);
            balance = balance.subtract(bigDecimals[i]);
        }
        bigDecimals[count - 1] = balance;

        return bigDecimals;
    }

}
